package com.example.demo.DBServer.thisDatabase.service.impl;

import com.example.demo.DBServer.thisDatabase.dao.ExecuteConditionDao;
import com.example.demo.DBServer.thisDatabase.service.ExecuteConditionService;
import com.example.demo.entity.ConditionDetailsEntity;
import com.example.demo.entity.ExecuteConditionEntity;
import com.example.demo.entity.ExecuteInformationEntity;
import com.example.demo.utils.CollectionUtil;
import com.example.demo.utils.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ExecuteConditionServiceImpl implements ExecuteConditionService {

    @Autowired
    private ExecuteConditionDao executeConditionDao;

    @Override
    public void saveExecuteCondition(ExecuteConditionEntity executeCondition) {
        List<ConditionDetailsEntity> conditionDetailsList = executeCondition.getConditionDetailsList();
        if(conditionDetailsList!=null && conditionDetailsList.size()>0){
            executeCondition.setConditionDetails(JSONUtil.objToJson(conditionDetailsList));
        }
        executeConditionDao.saveExecuteCondition(executeCondition);
        List<ExecuteConditionEntity> executeConditionList = executeCondition.getExecuteConditionList();
        if(executeConditionList == null){
            return;
        }
        for(ExecuteConditionEntity condition : executeConditionList){
            condition.setExecuteInformationId(executeCondition.getExecuteInformationId());
            condition.setParentConditionId(executeCondition.getId());
            if(CollectionUtil.isNotEmpty(condition.getConditionDetailsList())){
                condition.setConditionDetails(JSONUtil.objToJson(condition.getConditionDetailsList()));
            }
        }
        this.batchSaveExecuteCondition(executeConditionList);
    }

    @Override
    public void batchSaveExecuteCondition(List<ExecuteConditionEntity> configs) {
        if(configs==null || configs.size()==0){
            return;
        }
        executeConditionDao.batchSaveExecuteCondition(configs);
        List<ExecuteConditionEntity> needAddList = new ArrayList<>();
        for(ExecuteConditionEntity condition : configs){
            if(CollectionUtil.isNotEmpty(condition.getExecuteConditionList())){
                condition.getExecuteConditionList().forEach(con -> {
                    con.setExecuteInformationId(condition.getExecuteInformationId());
                    con.setParentConditionId(condition.getId());
                    if(CollectionUtil.isNotEmpty(con.getConditionDetailsList())){
                        con.setConditionDetails(JSONUtil.objToJson(con.getConditionDetailsList()));
                    }
                });
                needAddList.addAll(condition.getExecuteConditionList());
            }
        }
        batchSaveExecuteCondition(needAddList);
    }

    @Override
    public ExecuteConditionEntity findOneById(Long id) {
        ExecuteConditionEntity condition = executeConditionDao.findOneById(id);
        if(StringUtils.isNotBlank(condition.getConditionDetails())){
            List<ConditionDetailsEntity> conditionDetailsList = JSONUtil
                    .jsonToObj(condition.getConditionDetails(), new TypeReference<List<ConditionDetailsEntity>>(){});
            condition.setConditionDetailsList(conditionDetailsList);
        }
        return condition;
    }

    @Override
    public ExecuteConditionEntity findAllByExecuteInformationId(Long executeInformationId) {
        List<ExecuteConditionEntity> conditions = executeConditionDao.findAllByExecuteInformationId(executeInformationId);
        for(ExecuteConditionEntity condition : conditions){
            if(StringUtils.isNotBlank(condition.getConditionDetails())){
                List<ConditionDetailsEntity> conditionDetailsList = JSONUtil
                        .jsonToObj(condition.getConditionDetails(), new TypeReference<List<ConditionDetailsEntity>>(){});
                condition.setConditionDetailsList(conditionDetailsList);
            }
        }
        ExecuteConditionEntity headCondition = conditions.stream()
                .filter(con -> con.getParentConditionId()==null).findAny().orElse(null);
        Queue<ExecuteConditionEntity> queue = new LinkedList<>();
        queue.add(headCondition);
        while (!queue.isEmpty()){
            ExecuteConditionEntity executeCondition = queue.poll();
            List<ExecuteConditionEntity> entities = conditions.stream()
                    .filter(con -> executeCondition.getId().equals(con.getParentConditionId())).collect(Collectors.toList());
            executeCondition.setExecuteConditionList(entities);
            queue.addAll(entities);
        }
        return headCondition;
    }
}
